package Infix2RPM.processor.infixElement;


import org.apache.commons.lang.StringUtils;

import Infix2RPM.processor.Exception.BasicOperandException;
import Infix2RPM.processor.Exception.BasicOperatorException;
import Infix2RPM.processor.Exception.LogicException;
import Infix2RPM.processor.Stack.BasicOperand;

public class StringOperand implements BasicOperand {
	private String value = null;

	public StringOperand(String value) {
		this.value = value;
	}

	public StringOperand add(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof String)) {
			toss("Operand to add is not a String");
		}
		return new StringOperand(this.value + operand.getValue());
	}

	public StringOperand subtract(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof String)) {
			toss("Operand to subtract is not a String");
		}
		return new StringOperand(this.value.replace((String) operand.toString(), ""));
	}

	public StringOperand divide(BasicOperand operand)
			throws BasicOperatorException {
		throw new BasicOperatorException(
				"String division is unsupported", this.className());
	}

	public StringOperand multiply(BasicOperand operand)
			throws BasicOperandException {
		Integer multiplier = this.validAsInt((String) operand.getValue());
		this.value = StringUtils.repeat(value, multiplier);
		
		return new StringOperand(this.value);
	}

	public StringOperand power(BasicOperand exponent)
			throws BasicOperatorException {
		throw new BasicOperatorException(
				"String raised to power is unsupported", this.className());
	}

	public StringOperand concat(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof String)) {
			toss("Operand to subtract is not a String");
		}
		return new StringOperand(this.value + operand);
	}

	public StringOperand mod(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof String)) {
			toss("Operand to subtract is not a String");
		}
		return new StringOperand(this.value.replaceAll((String) operand.getValue(), ""));
	}

	public BooleanOperand equal(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof String)) {
			toss("Operand to == is not a String");
		}
		return new BooleanOperand(this.value.equals((String) operand.getValue()));
	}
	
	public BooleanOperand lessThan(BasicOperand operator)
			throws BasicOperatorException {
		throw new BasicOperatorException(
				"String operator < is unsupported", this.className());
	}

	public BooleanOperand lessThanEqual(BasicOperand operator)
			throws BasicOperatorException {
		throw new BasicOperatorException(
				"String operator <= is unsupported", this.className());
	}

	public BooleanOperand greaterThan(BasicOperand operator)
			throws BasicOperatorException {
		throw new BasicOperatorException(
				"String operator < is unsupported", this.className());
	}

	public BooleanOperand greaterThanEqual(BasicOperand operator)
			throws BasicOperatorException {
		throw new BasicOperatorException(
				"String operator >= is unsupported", this.className());
	}

	
	public BooleanOperand or(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"Logical OR using String is unsupported", this.className());
	}

	public BooleanOperand and(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"logical AND using String is unsupported", this.className());
	}
	public boolean isNull() {
		return this.value == null;
	}

	public boolean isEmpty() {
		return this.value.isEmpty();
	}

	public String getValue() {
		return this.value;
	}

	private Integer validAsInt(String evaluate) throws BasicOperandException {
		Integer ret = null;

		if (!(evaluate instanceof String)) {
			toss("Operand is not a String.");
		} else {

			try {
				ret = Integer.parseInt((String) evaluate);
			} catch (NumberFormatException e) {
				toss(evaluate + " is not an parseable Integer.");
			}
		}
		return ret;
	}

	private StringOperand toss(String message) throws BasicOperandException {
		throw new BasicOperandException(message, this.getClass().getName());
	}
	
	public String getValueAsString() {
		return this.value.toString();
	}
	
	public boolean isEqual(String token) {
		return this.value.toString().equals(token);
	}

	private String className() {
		return this.getClass().getName();
	}

}
